package ssq.gamest.websocketserver;

import java.io.BufferedReader; //#ifdef Java
import java.io.IOException; //#ifdef Java
import java.io.InputStreamReader; //#ifdef Java
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Collection;

import org.java_websocket.WebSocket;
import org.java_websocket.framing.Framedata;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;

import ssq.utils.AutoHelpParser;
import ssq.utils.LogUtils;
import ssq.utils.CmdLineParser.Option;

public class GameCommunicationServer extends WebSocketServer
{
    public GameCommunicationServer(int port) throws UnknownHostException
    {
        super(new InetSocketAddress(port));
    }

    public GameCommunicationServer(InetSocketAddress address)
    {
        super(address);
    }

    @Override
    public void onOpen(WebSocket conn, ClientHandshake handshake)
    {
        this.sendToAll("new connection: " + handshake.getResourceDescriptor());
        System.out.println(conn.getRemoteSocketAddress().getAddress().getHostAddress() + " entered the room!");
    }

    @Override
    public void onClose(WebSocket conn, int code, String reason, boolean remote)
    {
        this.sendToAll(conn + " has left the room!");
        System.out.println(conn + " has left the room!");
    }

    @Override
    public void onMessage(WebSocket conn, String message)
    {
        this.sendToAll(message);
        System.out.println(conn + ": " + message);
    }

    @Override
    public void onFragment(WebSocket conn, Framedata fragment)
    {
        System.out.println("received fragment: " + fragment);
    }

    public static void main(String[] args) throws UnknownHostException
    {
        runAndGetServer(args);
    }

    public static GameCommunicationServer runAndGetServer(String[] args) throws UnknownHostException
    {
        AutoHelpParser parser = new AutoHelpParser("WebSocketServer");
        Option<Integer> portO = parser.addHelp(parser.addIntegerOption('p', "port"), "Port to listen to", "44343");
            parser.parse(args);

        int port = parser.getOptionValue(portO, 44343);

        final GameCommunicationServer s = new GameCommunicationServer(port);

        //        try
        //        {
        //            // load up the key store
        //            String STORETYPE = "JKS";
        //            String KEYSTORE = DirUtils.getKeyRoot() + "server.jks";
        //            String STOREPASSWORD = "000000";
        //            
        //            SSLContext ctx = SSLContext.getInstance("SSL");
        //            
        //            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        //            TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
        //            
        //            KeyStore ks = KeyStore.getInstance(STORETYPE);
        //            KeyStore tks = KeyStore.getInstance(STORETYPE);
        //            
        //            ks.load(new FileInputStream(DirUtils.getKeyRoot() + "kserver.keystore"), STOREPASSWORD.toCharArray());
        //            tks.load(new FileInputStream(DirUtils.getKeyRoot() + "tserver.keystore"), STOREPASSWORD.toCharArray());
        //            
        //            kmf.init(ks, STOREPASSWORD.toCharArray());
        //            tmf.init(tks);
        //            
        //            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
        //            
        //            DefaultSSLWebSocketServerFactory sslf = new DefaultSSLWebSocketServerFactory(ctx);
        //            s.setWebSocketFactory(sslf);
        //        }
        //        catch (Exception e)
        //        {
        //            e.printStackTrace();
        //        }
        
        s.start();
        
        LogUtils.logString("GameCommunicationServer started on port: " + s.getPort(), "ws server", false);
        
        //##ifdef Java
        new Thread()
        {
            @Override
            public void run()
            {
        BufferedReader sysin = new BufferedReader(new InputStreamReader(System.in));
        while (true)
        {
                    String in;
                    try
                    {
                        in = sysin.readLine();
            s.sendToAll(in);
            if (in.equals("exit"))
            {
                s.stop();
                break;
            }
            else if (in.equals("restart"))
            {
                s.stop();
                s.start();
                break;
            }
        }
                    catch (Exception e)
                    {
                        e.printStackTrace();
                        try
                        {
                            s.stop();
                        }
                        catch (IOException e1)
                        {
                            e1.printStackTrace();
                        }
                        catch (InterruptedException e1)
                        {
                            e1.printStackTrace();
                        }
                    }
                }
            }
        }.start();
        //##end
        
        return s;
    }
    
    @Override
    public void onError(WebSocket conn, Exception ex)
    {
        ex.printStackTrace();
        if (conn != null)
        {
            // some errors like port binding failed may not be assignable to a specific websocket
        }
    }
    
    /**
     * Sends <var>text</var> to all currently connected WebSocket clients.
     * 
     * @param text
     *            The String to send across the network.
     * @throws InterruptedException
     *             When socket related I/O errors occur.
     */
    public void sendToAll(String text)
    {
        Collection<WebSocket> con = connections();
        synchronized (con)
        {
            for (WebSocket c : con)
            {
                c.send(text);
            }
        }
    }
}
